renderer = {
	new = function(name)
		local self = { file = io.open(name, "w") }
		setmetatable(self, { __index = renderer })
		return self
	end,
	
	close = function(self)
		self.file:close()
	end,
	
	p = function(self, ...)
		self.file:write(...)
	end,
	
	pl = function(self, ...)
		self:p(...)
		self.file:write("\n")
	end,
	
	encode = function(self, what)
		return common.xmlEncode(what)
	end,
	
	pe = function(self, text)
		if text == nil then return end
		assert(type(text) == "string")
		self:p(self:encode(text))
	end,
	
	pel = function(self, text)
		self:pe(text)
		self:pl()
	end,
	
	cssAttributes = function(self, values)
		if type(values) == "nil" then return "" end
		assert(type(values) == "table")
		local ret = ""
		for name, value in pairs(values) do
			ret = ret .. name .. ": " .. value .. "; "
		end
		return ret
	end,
	
	cssSheet = function(self, values)
		if values == nil then return end
		assert(type(values) == "table")
		local names = {}
		for name in pairs(values) do
			names[#names + 1] = name
		end
		table.sort(names)
		for i, name in pairs(names) do
			local value = values[name]
			self:pl(name, " { ", self:cssAttributes(value) , "}")
		end
	end,
	
	attributes = function(self, values)
		if type(values) == "string" then return values end
		if type(values) == "nil" then return "" end
		assert(type(values) == "table", "attributes must be string, nil or table")
		local ret = ""
		for name, value in pairs(values) do
			local svalue
			if type(value) == "string" then
				svalue = self:encode(value)
			else
				if type(value) == "number" then
					svalue = tostring(value)
				else
					assert(type(value) == "table", "only string, number or table allowed as attribute value")
					svalue = self:cssAttributes(value)
				end
			end
			ret = ret .. " " .. name .. "=\"" .. svalue .. "\""
		end
		return ret
	end,
	
	begin = function(self, name, attributes)
		self:p("<", name, self:attributes(attributes), ">");
	end,
	
	beginl = function(self, name, attributes)
		self:begin(name, attributes)
		self:pl()
	end,
	
	_end = function(self, name)
		self:p("</", name, ">");
	end,
	
	endl = function(self, name)
		self:_end(name)
		self:pl()
	end,
	
	empty = function(self, name, attributes)
		self:p("<", name, self:attributes(attributes), "/>");
	end,
	
	emptyl = function(self, name, attributes)
		self:empty(name, attributes)
		self:pl()
	end,
	
	element = function(self, name, attributes, text)
		if text == nil then
			self:empty(name, attributes)
		else
			self:begin(name, attributes)
			if type(text) == "function" then
				text()
			else
				assert(type(text) == "string", "text must be string, function or nil")
				self:pe(text)
			end
			self:_end(name)
		end
	end,
	
	elementl = function(self, name, attributes, text)
		if text == nil then
			self:emptyl(name, attributes)
		else
			self:beginl(name, attributes)
			if type(text) == "function" then
				text()
			else
				assert(type(text) == "string", "text must be string, function or nil")
				self:pe(text)
			end
			self:pl()
			self:endl(name)
		end
	end,
	
	comment = function(self, text)
		self:p("<!-- ")
		self:p(text)
		self:p("-->")
	end,
	
	xmlHeader = function(self, encoding)
		self:p("<?xml version=\"1.0\"")
		if encoding ~= nil then self:p(" encoding=\"", encoding, "\"") end
		self:pl("?>")
	end,
	
	doctype = function(self, _type)
		local root, id, uri
		if _type == "html-transitional" then
			root = "html"
			id = "-//W3C//DTD XHTML 1.0 Transitional//EN"
			uri = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
		end
		if _type == "html-strict" then
			root = "html"
			id = "-//W3C//DTD XHTML 1.0 Strict//EN"
			uri = "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
		end
		assert(root, "Unknown doctype")
		self:pl(string.format("<!DOCTYPE %s PUBLIC \"%s\" \"%s\">", root, id, uri))
	end,
	
	htmlBegin = function(self)
		self:beginl("html", { xmlns = "http://www.w3.org/1999/xhtml" })
	end,
	
	htmlEnd = function(self)
		self:endl("html")
	end,
	
	htmlDivBegin = function(self, css, attributes)
		if attributes == nil then attributes = {} end
		if css ~= nil then attributes.class = css end
		self:beginl("div", attributes)
	end,
	
	htmlDivEnd = function(self, css)
		self:_end("div")
		if css ~= nil then self:comment("." .. css) end
		self:pl()
	end,
	
	htmlDiv = function(self, css, attributes, content)
		self:htmlDivBegin(css, attributes)
		if content ~= nil then self:pe(content) end
		self:htmlDivEnd(css)
	end,
	
	htmlSpan = function(self, css, attributes, text)
		if attributes == nil then attributes = {} end
		if css ~= nil then attributes.class = css end
		self:elementl("span", attributes, text)
	end,
	
	svgBegin = function(self)
		self:beginl("svg", {
			xmlns = "http://www.w3.org/2000/svg",
			version = "1.1",
			preserveAspectRatio = "xMidYMid slice",
			style = {
				width = "100%",
				height = "100%",
				position = "absolute",
				top = 0,
				left = 0
			}
		})
	end,
	
	svgEnd = function(self)
		self:endl("svg")
	end
}


